package ru.ifmo.lab3;

import java.util.ArrayList;
import java.util.Random;
import java.util.concurrent.Semaphore;
import java.util.concurrent.CountDownLatch;

public class CockroachThread implements Runnable {
    private Graph graph;
    private Integer startVertex;
    private Integer currentVertex;
    private Integer finishVertex;
    private String cockroachNumber;
    private CountDownLatch countDownLatch;

    private final int minTimeInterval = 500;
    private final int maxTimeInterval = 2000;


    public CockroachThread(Graph graph, Integer startVertex, Integer finishVertex, Integer cockroachNumber, CountDownLatch countDownLatch) {
        this.graph = graph;
        this.startVertex = startVertex;
        this.finishVertex = finishVertex;
        this.currentVertex = startVertex;
        this.cockroachNumber = Integer.toString(cockroachNumber);
        this.countDownLatch = countDownLatch;

    }

    private String getCockroachStringHeader() {
        return "Cockroach № " + cockroachNumber;
    }

    @Override
    public void run() {
        System.out.println(getCockroachStringHeader() + " has appeared in vertex " + currentVertex);

        Random random = new Random();
        Semaphore semaphore = null;
        boolean isAcquire = false;

        try {
            while (!currentVertex.equals(finishVertex)) {
                ArrayList<Integer> vertexes = graph.getAdjVertexes(currentVertex);

                if (vertexes.size() == 0 && !currentVertex.equals(finishVertex)) {
                    System.out.println("(Zzz)" + getCockroachStringHeader() + " is deadlocked in vertex " + currentVertex);
                    break;
                }

                Integer targetVertex = vertexes.get(random.nextInt(vertexes.size()));
                semaphore = graph.getEdgeSemaphore(currentVertex, targetVertex);

                semaphore.acquire();
                isAcquire = true;

                int timeInterval = random.nextInt((maxTimeInterval - minTimeInterval) + 1) + minTimeInterval;
                System.out.println(getCockroachStringHeader() + " has moved from vertex " + currentVertex + " to vertex " + targetVertex + ", delay = " + timeInterval + " ms");
                Thread.sleep(timeInterval);
                System.out.println(getCockroachStringHeader() + " successfully reached vertex " + targetVertex);

                semaphore.release();
                isAcquire = false;

                currentVertex = targetVertex;
            }

            System.out.println("(!!!)" + getCockroachStringHeader() + " has reached end!");
        }
        catch (IllegalStateException e) {
            System.out.println(e.getMessage());
        }
        catch (InterruptedException e) {
            System.err.println(e.getMessage());
            Thread.currentThread().interrupt();
        }
        finally {
            System.out.println(getCockroachStringHeader() + " is stopped!");
            if (semaphore != null && isAcquire) {
                semaphore.release();
            }
            countDownLatch.countDown();
        }
    }
}
